package com.epam.cdp.selenium2.core.ui.elements;

import javax.xml.bind.JAXBElement;

import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;

import com.epam.cdp.selenium2.core.results.logger.Logger;
import com.epam.cdp.selenium2.core.ui.Browser;
import com.epam.cdp.selenium2.core.ui.locators_map.ElementAttributes;
import com.epam.cdp.selenium2.core.ui.locators_map.ElementInfoContainer;

/**
 * @author akhachaturan
 */
public class Element
{

  protected ElementInfoContainer elementInfoContainer;

  protected WebElement element;

  public Element( ElementInfoContainer container )
  {
    this.elementInfoContainer = container;
  }

  protected void initElement()
  {
    if( element == null )
    {
      for( ElementAttributes att : ElementAttributes.values() )
      {
        /** SEARCH BY XPATH */
        if( ( att == ElementAttributes.XPATH ) && ( elementInfoContainer.getSpecifiedXpath() != null ) )
        {
          try
          {
            element = Browser.getBrowser().findElement( By.xpath( elementInfoContainer.getSpecifiedXpath() ) );
            Logger.info( this.getClass().getSimpleName() + " '" + elementInfoContainer.getName()
              + "' was found by xpath" );
            return;
          }
          catch( Exception e )
          {
            throw new RuntimeException( "Element '" + elementInfoContainer.getName() + "' not found by XPATH '"
              + elementInfoContainer.getSpecifiedXpath() + "'" );
          }
        }

        /** SEARCH BY XPATTERN */
        if( ( att == ElementAttributes.XPATTERN ) && ( elementInfoContainer.getSpecifiedXpattern() != null ) )
        {
          if( elementInfoContainer.getComposite() == null )
          {
            throw new RuntimeException( "Please provide data for compose full XPATH from provided XPATTERN" );
          }
          try
          {
            @SuppressWarnings( "all" )
            String fullComposedXpath =
              String.format( elementInfoContainer.getSpecifiedXpattern(), elementInfoContainer.getComposite() );
            element = Browser.getBrowser().findElement( By.xpath( fullComposedXpath ) );
            Logger.info( this.getClass().getSimpleName() + " '" + elementInfoContainer.getName()
              + "' was found by xpattern" );
            return;
          }
          catch( Exception e )
          {
            throw new RuntimeException( "Element '" + elementInfoContainer.getName() + "' not found by XPATTERN '"
              + elementInfoContainer.getSpecifiedXpattern() + "'" );
          }
        }

        if( elementInfoContainer.getSearchCriterias() != null && ( att != ElementAttributes.XPATH )
          && ( att != ElementAttributes.XPATTERN ) )
        {
          for( JAXBElement<String> locator : elementInfoContainer.getSearchCriterias() )
          {
            if( att.toString().toLowerCase().equals( locator.getName().getLocalPart() ) )
            {
              element = findElement( att, locator.getValue() );
              if( element != null )
              {
                return;
              }
              break;
            }
          }
        }
      }
    }
  }

  private WebElement findElement( ElementAttributes attribute, String searchCriteria )
  {
    WebElement element = null;
    switch( attribute )
    {
      case ID:
        try
        {
          element = Browser.getBrowser().findElement( By.id( searchCriteria ) );
        }
        catch( Exception e )
        {
        }
        break;

      case NAME:
        try
        {
          element = Browser.getBrowser().findElement( By.name( searchCriteria ) );
        }
        catch( Exception e )
        {
        }
        break;

      case CLASS:
        try
        {
          element = Browser.getBrowser().findElement( By.className( searchCriteria ) );
        }
        catch( Exception e )
        {
        }
        break;
    }
    if( element == null )
    {
      Logger.warn( "Element '" + elementInfoContainer.getName() + "' not found by attribute '"
        + attribute.toString().toLowerCase() + "' with criteria '" + searchCriteria + "'" );
    }
    return element;
  }

  public boolean isElementAvailable()
  {
    initElement();
    return element.isEnabled();
  }

  public void click()
  {
    initElement();
    Logger.operation( "Click on " + this.getClass().getSimpleName() + " '" + elementInfoContainer.getName() + "'" );
    element.click();
  }

  public String readText()
  {
    initElement();
    return element.getText();
  }

  public String getValue()
  {
    initElement();
    return element.getValue();
  }

}